/**
 * @copyright Copyright (c) 2025 CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author Chen Yongjie
 */
#include "test_uart.h"
#include <stdint.h> 
// 声明被测试的静态函数
extern uint8_t set_opt(int fd, uint32_t baudRate, uint8_t wordlength, char parity, uint8_t stopBit);

/**
 * @brief 测试set_opt函数在正常参数下的行为
 * 
 * 测试步骤：
 * 1. 打开一个有效的串口设备
 * 2. 使用正常的参数调用set_opt函数
 * 3. 验证返回值和串口配置
 * 
 * 预期结果：
 * 1. 函数返回0表示成功
 * 2. 串口参数被正确设置
 */
void test_set_opt_normal(void)
{
    // 打开一个测试用的串口设备
    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd != -1)
    {
        // 测试正常参数
        uint8_t result = set_opt(fd, 115200, 8, 'N', 1);
        CU_ASSERT_EQUAL(result, 0);
        
        // 验证串口配置
        struct termios opt;
        tcgetattr(fd, &opt);
        
        // 验证波特率设置
        CU_ASSERT_EQUAL(cfgetispeed(&opt), B115200);
        CU_ASSERT_EQUAL(cfgetospeed(&opt), B115200);
        
        // 验证数据位设置
        CU_ASSERT_TRUE((opt.c_cflag & CS8) == CS8);
        
        // 验证校验位设置
        CU_ASSERT_TRUE((opt.c_cflag & PARENB) == 0);
        
        // 验证停止位设置
        CU_ASSERT_TRUE((opt.c_cflag & CSTOPB) == 0);
        
        close(fd);
    }
}

/**
 * @brief 测试set_opt函数在无效文件描述符下的行为
 * 
 * 测试步骤：
 * 1. 使用无效的文件描述符调用set_opt函数
 * 
 * 预期结果：
 * 1. 函数返回-1表示错误
 */
void test_set_opt_invalid_fd(void)
{
    uint8_t result = set_opt(-1, 115200, 8, 'N', 1);
    CU_ASSERT_EQUAL(result, -1);
}

/**
 * @brief 测试set_opt函数在无效波特率下的行为
 * 
 * 测试步骤：
 * 1. 打开一个有效的串口设备
 * 2. 使用无效的波特率调用set_opt函数
 * 
 * 预期结果：
 * 1. 函数应该使用默认波特率9600
 */
void test_set_opt_invalid_baudrate(void)
{
    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd != -1)
    {
        uint8_t result = set_opt(fd, 1000, 8, 'N', 1);
        CU_ASSERT_EQUAL(result, 0);
        
        struct termios opt;
        tcgetattr(fd, &opt);
        
        // 验证是否使用默认波特率
        CU_ASSERT_EQUAL(cfgetispeed(&opt), B9600);
        CU_ASSERT_EQUAL(cfgetospeed(&opt), B9600);
        
        close(fd);
    }
}

/**
 * @brief 测试set_opt函数在无效字长下的行为
 * 
 * 测试步骤：
 * 1. 打开一个有效的串口设备
 * 2. 使用无效的字长参数调用set_opt函数
 * 
 * 预期结果：
 * 1. 函数应该正确处理无效字长
 */
void test_set_opt_invalid_wordlength(void)
{
    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd != -1)
    {
        uint8_t result = set_opt(fd, 115200, 6, 'N', 1);
        CU_ASSERT_EQUAL(result, 0);
        
        struct termios opt;
        tcgetattr(fd, &opt);
        
        // 验证字长设置
        CU_ASSERT_TRUE((opt.c_cflag & CSIZE) != CS6);
        
        close(fd);
    }
}

/**
 * @brief 测试set_opt函数在无效校验位下的行为
 * 
 * 测试步骤：
 * 1. 打开一个有效的串口设备
 * 2. 使用无效的校验位参数调用set_opt函数
 * 
 * 预期结果：
 * 1. 函数应该正确处理无效校验位
 */
void test_set_opt_invalid_parity(void)
{
    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd != -1)
    {
        uint8_t result = set_opt(fd, 115200, 8, 'X', 1);
        CU_ASSERT_EQUAL(result, 0);
        
        struct termios opt;
        tcgetattr(fd, &opt);
        
        // 验证校验位设置
        CU_ASSERT_TRUE((opt.c_cflag & PARENB) == 0);
        
        close(fd);
    }
}

/**
 * @brief 测试set_opt函数在无效停止位下的行为
 * 
 * 测试步骤：
 * 1. 打开一个有效的串口设备
 * 2. 使用无效的停止位参数调用set_opt函数
 * 
 * 预期结果：
 * 1. 函数应该正确处理无效停止位
 */
void test_set_opt_invalid_stopbit(void)
{
    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd != -1)
    {
        uint8_t result = set_opt(fd, 115200, 8, 'N', 3);
        CU_ASSERT_EQUAL(result, 0);
        
        struct termios opt;
        tcgetattr(fd, &opt);
        
        // 验证停止位设置
        CU_ASSERT_TRUE((opt.c_cflag & CSTOPB) == 0);
        
        close(fd);
    }
}

/**
 * @brief 测试uart_init函数在正常参数下的行为
 * 
 * 测试步骤：
 * 1. 使用正常的参数调用uart_init函数
 * 2. 验证返回值和串口是否正确打开
 * 3. 清理资源
 * 
 * 预期结果：
 * 1. 函数返回0表示成功
 * 2. 串口被正确打开和配置
 */
void test_uart_init_normal(void)
{
    uint8_t result = uart_init(UART_PORT, 115200, 8, 'N', 1);
    CU_ASSERT_EQUAL(result, 0);
    CU_ASSERT_NOT_EQUAL(UART_FD, -1);
    
    // 清理资源
    uart_destory();
}

/**
 * @brief 测试uart_init函数在无效串口端口下的行为
 * 
 * 测试步骤：
 * 1. 使用不存在的串口端口调用uart_init函数
 * 
 * 预期结果：
 * 1. 函数返回-1表示错误
 * 2. UART_FD保持为-1
 */
void test_uart_init_invalid_port(void)
{
    uint8_t result = uart_init("/dev/ttyUSB99", 115200, 8, 'N', 1);
    CU_ASSERT_EQUAL(result, -1);
    CU_ASSERT_EQUAL(UART_FD, -1);
}

/**
 * @brief 测试uart_init函数在无效波特率下的行为
 * 
 * 测试步骤：
 * 1. 使用无效的波特率调用uart_init函数
 * 
 * 预期结果：
 * 1. 函数应该使用默认波特率9600并成功返回
 */
void test_uart_init_invalid_baudrate(void)
{
    uint8_t result = uart_init(UART_PORT, 1000, 8, 'N', 1);
    CU_ASSERT_EQUAL(result, 0);
    
    // 验证是否使用默认波特率
    struct termios opt;
    tcgetattr(UART_FD, &opt);
    CU_ASSERT_EQUAL(cfgetispeed(&opt), B9600);
    CU_ASSERT_EQUAL(cfgetospeed(&opt), B9600);
    
    uart_destory();
}

/**
 * @brief 测试uart_init函数在无效字长下的行为
 * 
 * 测试步骤：
 * 1. 使用无效的字长参数调用uart_init函数
 * 
 * 预期结果：
 * 1. 函数应该使用默认字长8并成功返回
 */
void test_uart_init_invalid_wordlength(void)
{
    uint8_t result = uart_init(UART_PORT, 115200, 6, 'N', 1);
    CU_ASSERT_EQUAL(result, 0);
    
    struct termios opt;
    tcgetattr(UART_FD, &opt);
    CU_ASSERT_TRUE((opt.c_cflag & CS8) == CS8);
    
    uart_destory();
}

/**
 * @brief 测试uart_init函数在无效校验位下的行为
 * 
 * 测试步骤：
 * 1. 使用无效的校验位参数调用uart_init函数
 * 
 * 预期结果：
 * 1. 函数应该使用默认无校验并成功返回
 */
void test_uart_init_invalid_parity(void)
{
    uint8_t result = uart_init(UART_PORT, 115200, 8, 'X', 1);
    CU_ASSERT_EQUAL(result, 0);
    
    struct termios opt;
    tcgetattr(UART_FD, &opt);
    CU_ASSERT_TRUE((opt.c_cflag & PARENB) == 0);
    
    uart_destory();
}

/**
 * @brief 测试uart_init函数在无效停止位下的行为
 * 
 * 测试步骤：
 * 1. 使用无效的停止位参数调用uart_init函数
 * 
 * 预期结果：
 * 1. 函数应该使用默认停止位1并成功返回
 */
void test_uart_init_invalid_stopbit(void)
{
    uint8_t result = uart_init(UART_PORT, 115200, 8, 'N', 3);
    CU_ASSERT_EQUAL(result, 0);
    
    struct termios opt;
    tcgetattr(UART_FD, &opt);
    CU_ASSERT_TRUE((opt.c_cflag & CSTOPB) == 0);
    
    uart_destory();
}

/**
 * @brief 测试uart_init函数对空指针参数的处理
 * 
 * 测试步骤：
 * 1. 使用NULL作为uart_port参数调用uart_init函数
 * 2. 验证返回值和UART_FD的状态
 * 
 * 预期结果：
 * 1. 函数应返回-1表示错误
 * 2. UART_FD应保持为-1
 */
void test_uart_init_null_port(void)
{
    // 保存原始的UART_FD值
    int original_fd = UART_FD;
    
    // 使用NULL作为端口参数
    uint8_t result = uart_init(NULL, 115200, 8, 'N', 1);
    
    // 验证返回值
    CU_ASSERT_EQUAL(result, -1);
    
    // 验证UART_FD未被修改
    CU_ASSERT_EQUAL(UART_FD, original_fd);
}

/**
 * @brief 测试serial_send函数在正常情况下的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 准备测试数据
 * 3. 调用serial_send函数发送数据
 * 4. 验证返回值
 * 5. 清理资源
 * 
 * 预期结果：
 * 1. 函数返回实际写入的字节数
 * 2. 返回值等于请求发送的字节数
 */
void test_serial_send_normal(void)
{
    // 初始化串口
    uint8_t init_result = uart_init(UART_PORT, 115200, 8, 'N', 1);
    if (init_result == 0)
    {
        // 准备测试数据
        uint8_t test_data[] = "Hello UART";
        uint16_t test_len = strlen((char *)test_data);
        
        // 发送数据
        uint16_t write_num = serial_send(test_data, test_len);
        
        // 验证返回值
        CU_ASSERT_EQUAL(write_num, test_len);
        
        // 清理资源
        uart_destory();
    }
}

/**
 * @brief 测试serial_send函数在buffer为NULL时的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 调用serial_send函数，传入NULL buffer
 * 3. 验证返回值
 * 4. 清理资源
 * 
 * 预期结果：
 * 1. 函数返回0表示未写入任何数据
 */
void test_serial_send_null_buffer(void)
{
    // 初始化串口
    uint8_t init_result = uart_init(UART_PORT, 115200, 8, 'N', 1);
    if (init_result == 0)
    {
        // 测试NULL buffer
        uint16_t write_num = serial_send(NULL, 10);
        
        // 验证返回值
        CU_ASSERT_EQUAL(write_num, 0);
        
        // 清理资源
        uart_destory();
    }
}

/**
 * @brief 测试serial_send函数在长度为0时的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 准备测试数据
 * 3. 调用serial_send函数，传入长度为0
 * 4. 验证返回值
 * 5. 清理资源
 * 
 * 预期结果：
 * 1. 函数返回0表示未写入任何数据
 */
void test_serial_send_zero_length(void)
{
    // 初始化串口
    uint8_t init_result = uart_init(UART_PORT, 115200, 8, 'N', 1);
    if (init_result == 0)
    {
        // 准备测试数据
        uint8_t test_data[] = "Test Data";
        
        // 测试长度为0
        uint16_t write_num = serial_send(test_data, 0);
        
        // 验证返回值
        CU_ASSERT_EQUAL(write_num, 0);
        
        // 清理资源
        uart_destory();
    }
}

/**
 * @brief 测试serial_send函数在文件描述符无效时的行为
 * 
 * 测试步骤：
 * 1. 准备测试数据
 * 2. 将UART_FD设置为无效值
 * 3. 调用serial_send函数
 * 4. 验证返回值
 * 
 * 预期结果：
 * 1. 函数返回0表示未写入任何数据
 */
void test_serial_send_invalid_fd(void)
{
    // 准备测试数据
    uint8_t test_data[] = "Test Data";
    uint16_t test_len = strlen((char *)test_data);
    
    // 设置无效的文件描述符
    UART_FD = -1;
    
    // 测试发送
    uint16_t write_num = serial_send(test_data, test_len);
    
    // 验证返回值
    CU_ASSERT_EQUAL(write_num, 0);
}

/**
 * @brief 测试serial_recv函数在正常情况下的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 准备接收缓冲区
 * 3. 调用serial_recv函数
 * 4. 验证接收结果
 * 
 * 预期结果：
 * 1. 函数返回实际读取的字节数
 * 2. 接收缓冲区包含正确的数据
 */
void test_serial_recv_normal(void) {
    uint8_t buffer[256] = {0};
    uint16_t len = sizeof(buffer);
    
    // 初始化串口
    if (uart_init(UART_PORT, 115200, 8, 'N', 1) == 0) {
        // 模拟发送数据到串口
        uint8_t test_data[] = "Test Data";
        write(UART_FD, test_data, strlen((char *)test_data));
        
        // 接收数据
        uint16_t read_num = serial_recv(buffer, len);
        
        // 验证接收结果
        CU_ASSERT_TRUE(read_num > 0);
        CU_ASSERT_NSTRING_EQUAL(buffer, test_data, read_num);
        
        uart_destory();
    }
}

/**
 * @brief 测试serial_recv函数在缓冲区为NULL时的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 使用NULL缓冲区调用serial_recv
 * 
 * 预期结果：
 * 1. 函数应返回0
 * 2. 不应发生段错误
 */
void test_serial_recv_null_buffer(void) {
    if (uart_init(UART_PORT, 115200, 8, 'N', 1) == 0) {
        uint16_t read_num = serial_recv(NULL, 10);
        CU_ASSERT_EQUAL(read_num, 0);
        uart_destory();
    }
}

/**
 * @brief 测试uart_destory函数在多次调用时的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 多次调用uart_destory
 * 
 * 预期结果：
 * 1. 第一次调用应成功
 * 2. 后续调用应返回错误
 */
void test_uart_destory_multiple_calls(void) {
    // 初始化串口
    if (uart_init(UART_PORT, 115200, 8, 'N', 1) == 0) {
        // 第一次调用
        uint8_t result1 = uart_destory();
        CU_ASSERT_EQUAL(result1, 0);
        
        // 第二次调用
        uint8_t result2 = uart_destory();
        CU_ASSERT_EQUAL(result2, -1);
        
        // 验证UART_FD已被关闭
        CU_ASSERT_EQUAL(UART_FD, -1);
    }
}

/**
 * @brief 测试串口在高频读写操作下的行为
 * 
 * 测试步骤：
 * 1. 初始化串口
 * 2. 快速交替执行读写操作
 * 3. 验证数据完整性
 * 
 * 预期结果：
 * 1. 所有操作应成功完成
 * 2. 数据应保持完整
 */
void test_uart_high_frequency_operations(void) {
    if (uart_init(UART_PORT, 115200, 8, 'N', 1) == 0) {
        uint8_t send_buffer[32] = "Test Data";
        uint8_t recv_buffer[32] = {0};
        uint16_t len = strlen((char *)send_buffer);
        
        // 执行多次读写操作
        for (int i = 0; i < 100; i++) {
            uint16_t write_num = serial_send(send_buffer, len);
            CU_ASSERT_EQUAL(write_num, len);
            
            uint16_t read_num = serial_recv(recv_buffer, len);
            CU_ASSERT_TRUE(read_num >= 0);
        }
        
        uart_destory();
    }
}

/**
 * @brief 测试串口在不同波特率下的稳定性
 * 
 * 测试步骤：
 * 1. 使用不同波特率初始化串口
 * 2. 执行读写操作
 * 3. 验证操作结果
 * 
 * 预期结果：
 * 1. 所有支持的波特率都能正常工作
 * 2. 数据传输正确
 */
void test_uart_different_baudrates(void) {
    uint32_t baudrates[] = {2400, 4800, 9600, 115200};
    uint8_t test_data[] = "Test Data";
    uint16_t len = strlen((char *)test_data);
    
    for (int i = 0; i < sizeof(baudrates)/sizeof(baudrates[0]); i++) {
        if (uart_init(UART_PORT, baudrates[i], 8, 'N', 1) == 0) {
            // 测试发送
            uint16_t write_num = serial_send(test_data, len);
            CU_ASSERT_EQUAL(write_num, len);
            
            uart_destory();
        }
    }
}

/**
 * @brief 测试串口在不同校验位设置下的行为
 * 
 * 测试步骤：
 * 1. 使用不同校验位设置初始化串口
 * 2. 执行数据传输
 * 3. 验证传输结果
 * 
 * 预期结果：
 * 1. 所有校验位设置都能正常工作
 * 2. 数据传输正确
 */
void test_uart_different_parity(void) {
    char parity_options[] = {'N', 'E', 'O'};
    uint8_t test_data[] = "Test Data";
    uint16_t len = strlen((char *)test_data);
    
    for (int i = 0; i < sizeof(parity_options); i++) {
        if (uart_init(UART_PORT, 115200, 8, parity_options[i], 1) == 0) {
            uint16_t write_num = serial_send(test_data, len);
            CU_ASSERT_EQUAL(write_num, len);
            
            uart_destory();
        }
    }
}